home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / trace1a.arc / TRACE1.ASM < prev    next >
Encoding:
Assembly Source File  |  1987-02-04  |  41.9 KB  |  1,332 lines

  1.         page    60,132
  2.         .lfcond
  3.         title   "TRACE - Interrupt Tracer"
  4.         subttl  Introduction
  5.         page
  6.         comment \
  7.  
  8. TRACE is an INT tracer. It traps INT's, traces the registers at the entry
  9. to the INT, executes the INT itself, and then traces the regs at exit from
  10. the INT. It also allows the user at the keyboard to see all of this traced
  11. information, either at the screen or on the printer.
  12.  
  13. The INT's that are to be traced are specified in the source code (see config
  14. section below). Once defined, they may be enabled or disabled from the
  15. keyboard.
  16.  
  17.       <<< REBOOT AS SOON AS POSSIBLE AFTER INVOKING TRACE!!! >>>
  18.  
  19. This is not foolproof or bugfree. We use it 'cause it's a terrific tool
  20. for deprotecting copy-protected software. You use it at your own risk.
  21. When you've gotten a printout of the trace activity that interests you,
  22. reboot your system. Don't say that we didn't warn you.
  23.  
  24. Enjoy.
  25.  
  26.  
  27.       Usage is: TRACE [size]  
  28.  
  29.           where: size is the size of the trace table in K
  30.                  between 10 and 63, default is 30
  31.  
  32.  
  33. Known problems:
  34.  
  35.       Programs that use:  INT 21 function E0
  36.  
  37.       and Relay Gold Release 2.0
  38.  
  39.  
  40.         \
  41.         page
  42. code    segment para public 'code'
  43.         assume  cs:code,ds:code
  44.         public  trace_begin,trace_curr,trace_end,trace_bytes
  45.         public  ict_index,hndlr_index,prt_base
  46.         public  our_cs,test_cs,prtsc,periscope
  47.         public  rec_sizes,interp
  48.  
  49.         extrn   selvideo:near,selprint:near,print:near,print_hex:near
  50.         extrn   print_word:near,print_wordb:near,crlf:near,print_line:near
  51.         extrn   print_seg:near,print_dec:near,table_print:near
  52.         extrn   print_edit:near,feed:near,key:near,zap_hits:near
  53.         
  54.         extrn   do_traces:near,do_enable:near,disp_active:near,do_fcb:near
  55.         extrn   init:near
  56.  
  57.         extrn   trace_table:byte
  58.  
  59.         org     0100h
  60. start:  jmp     init
  61.  
  62.         include trace1e.aic
  63.  
  64.  
  65. ; note that the number of ict's is set by number_icts in trace1e.aic 
  66. ;      and implicetly in code throughout this module.
  67.  
  68. ; note that you need an ICT for some INT 21h AH = 0F0h for the
  69. ;      detection of TRACE already being installed feature to work
  70. ;      ICT with low ah = 0dh  and high ah = ffh works fine.
  71.  
  72. ;      ict parms are:
  73. ;          flags,flags2,int,low ah, high ah, saved cs:ip, 
  74. ;          count of entries,ict number
  75.  
  76. ;      ict flags are:
  77. ;          f_active tracing on at start-up
  78. ;          f_ret    far ret with original flags, flags on stack
  79. ;          f_ret2   far ret with updated flags, no flags on stack
  80. ;          f_iret   iret with original flags, no flags on stack
  81.  
  82. ;      ict flags2 are:
  83. ;          f_call   This call will return. Example INT 21H, in general 
  84.  
  85. ict0  ICT  <F_ACTIVE+F_RET2+F_ENABLE,F_CALL,013H,0,0ffh,0,0,0>            
  86.                                                       ;ROM BIOS INT 13h (all)
  87. ict1  ICT  <F_ACTIVE+F_RET+F_ENABLE,0,020h,0,0ffh,0,0,1>        
  88.                                                       ;DOS EXIT
  89. ict2  ICT  <F_ACTIVE+F_RET2,F_CALL,021H,0,0ch,0,0,2>                      
  90.                                                       ;DOS funcs 00h thru 0Ch
  91. ict3  ICT  <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,F_CALL,021H,0dh,030h,0,0,3>    
  92.                                                       ;DOS func  0Dh  thru 030h 
  93. ict4  ICT  <F_ACTIVE+F_RET+F_ENABLE,0,021H,031h,031h,0,0,4>   
  94.                                                       ;DOS func  031h TSR
  95. ict5  ICT  <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,F_CALL,021H,032h,04Bh,0,0,5>   
  96.                                                       ;DOS funcs 032h thru 4Bh
  97. ict6  ICT  <F_ACTIVE+F_RET2+F_ENABLE,0,021H,04Ch,04Ch,0,0,6>   
  98.                                                       ;DOS func  04Ch  EXIT
  99. ict7  ICT  <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,F_CALL,021H,04Dh,0ffh,0,0,7>   
  100.                                                       ;DOS funcs 04Dh thru FFh
  101. ict8  ICT  <F_ACTIVE+F_RET+F_ENABLE,F_CALL,025h,0,0ffh,0,0,8>             
  102.                                                       ;RAW disk I/O
  103. ict9  ICT  <F_ACTIVE+F_RET+F_ENABLE,F_CALL,026h,0,0ffh,0,0,9>             
  104.                                                       ;RAW disk I/O
  105. ict10 ICT  <F_ACTIVE+F_RET+F_ENABLE,0,027h,0,0ffh,0,0,10>             
  106.                                                       ;DOS TSR
  107. ict11 ICT  <F_ACTIVE+F_RET2+F_ENABLE,0,02Eh,0,0ffh,0,0,11>             
  108.                                                       ;DOS undocumented .BAT call
  109.  
  110. ict12 ICT  <0,0,0,0,0,0,12>                                        ;unused
  111. ict13 ICT  <0,0,0,0,0,0,13>                                        ;unused
  112. ict14 ICT  <0,0,0,0,0,0,14>                                        ;unused
  113. ict15 ICT  <0,0,0,0,0,0,15>                                        ;unused
  114.  
  115.  
  116. ;*******************************************************
  117. ;    E N D    C O N F I G U R A T I O N
  118. ;*******************************************************
  119.  
  120.         subttl  Resident Storage
  121.         page
  122.  
  123. ;
  124. ; Things defined here are present even after we become resident and
  125. ; exit to DOS.
  126. ;
  127.  
  128.  
  129. ;********************************************************
  130. ;
  131. ; Index table pointing to all ICT's
  132. ;
  133. ;********************************************************
  134.  
  135. ict_index label word
  136.         dw      offset ict0
  137.         dw      offset ict1
  138.         dw      offset ict2
  139.         dw      offset ict3
  140.         dw      offset ict4
  141.         dw      offset ict5
  142.         dw      offset ict6
  143.         dw      offset ict7
  144.         dw      offset ict8
  145.         dw      offset ict9
  146.         dw      offset ict10
  147.         dw      offset ict11
  148.         dw      offset ict12
  149.         dw      offset ict13
  150.         dw      offset ict14
  151.         dw      offset ict15
  152.  
  153. ;********************************************************
  154. ;
  155. ; Index table pointing to all handlers
  156. ;
  157. ;********************************************************
  158.  
  159. hndlr_index label word
  160.         dw      offset handler0
  161.         dw      offset handler1
  162.         dw      offset handler2
  163.         dw      offset handler3
  164.         dw      offset handler4
  165.         dw      offset handler5
  166.         dw      offset handler6
  167.         dw      offset handler7
  168.         dw      offset handler8
  169.         dw      offset handler9
  170.         dw      offset handler10
  171.         dw      offset handler11
  172.         dw      offset handler12
  173.         dw      offset handler13
  174.         dw      offset handler14
  175.         dw      offset handler15
  176.  
  177. ;********************************************************
  178. ;
  179. ; Trace table pointers. Actual trace table slung over
  180. ;                       initialization code in TRACE12.ASM
  181. ;
  182. ;********************************************************
  183.  
  184. trace_begin      dw      offset trace_table      ;address of trace table begin 
  185. trace_curr       dw      offset trace_table      ;address of next entry
  186. trace_end        dw      offset trace_table      ;address of end of trace table
  187. trace_bytes      dw      trace_size              ;size of trace table  in bytes
  188.  
  189. ;********************************************************
  190. ;
  191. ; Table of sizes for each trace record type. Must be in same
  192. ; order as record types themselves.
  193. ;
  194. ;********************************************************
  195.  
  196. rec_sizes       label   word
  197.                 dw      size BEFORE
  198.                 dw      size AFTER
  199.                 dw      size FCB
  200.                 dw      size ASCIIZ
  201.  
  202. ;********************************************************
  203. ;
  204. ; Table of INT 21h functions that include an FCB pointer in DS:DX
  205. ;
  206. ;********************************************************
  207.  
  208. FCB_table       label   byte
  209.                 db      0fh,10h,11h,12h,13h,14h,15h,16h,17h,21h,22h,23h,24h,27h,28h
  210. FCB_end         label   byte
  211.  
  212.  
  213. ;********************************************************
  214. ;
  215. ; Table of INT 21h functions that include an ASCIIZ pointer in DS:DX
  216. ;
  217. ;********************************************************
  218.  
  219. ASCIIZ_table    label   byte
  220.                 db      4bh,3ch,3dh,41h,43h,4eh,56h,5ah,5bh,39h,3ah,3bh
  221. ASCIIZ_end      label   byte
  222.  
  223. ;********************************************************
  224. ;
  225. ; Misc storage
  226. ;
  227. ;********************************************************
  228.  
  229. our_cs          dw      0                       ;our CS (not for segment checking)
  230. test_cs         dw      0                       ;our normalized CS (for segment checking)
  231. long_addr       dd      0                       ;for long JMP's and CALLs
  232. our_ICT         dw      0                       ;for quick save of our ICT pointer
  233. our_flags       db      0                       ;for quick save of our ICT flags
  234. prt_base        dw      0                       ;base I/O address of printer
  235. ;prt_flag        db      0                       ;non-zero to send output to printer
  236.                 db      255 dup (0)             ;stack for Periscope Int handler
  237. our_tos         dw      0                       ;top of that stack
  238. stack_inuse     db      0                       ;non-zero when above stack is in use
  239. save_ss         dw      0                       ;for stack-swapping
  240. save_sp         dw      0
  241.  
  242.  
  243.         subttl  Interrupt Trappers and Tracing
  244.         page
  245.  
  246. ;********************************************************
  247. ;
  248. ; Interrupt handler entry points for each ICT
  249. ;
  250. ;********************************************************
  251.  
  252. handler macro   ictloc
  253.         cli                             ;*** NO INTERRUPTS!!! ***
  254.         push    bp                      ;save stack pointer, so that...
  255.         mov     bp,sp                   ;...we can ref things via BP
  256.         push    bx                      ;set BX to point to ICT
  257.         mov     bx,offset cs:ictloc
  258.         jmp     int_common              ;goto common code
  259.         endm
  260.  
  261. interrupt proc  far
  262.  
  263. handler0:
  264.         handler ict0
  265.  
  266. handler1:
  267.         handler ict1
  268.  
  269. handler2:
  270.         handler ict2
  271.  
  272. handler3:
  273.         handler ict3
  274.  
  275. handler4:
  276.         handler ict4
  277.  
  278. handler5:
  279.         handler ict5
  280.  
  281. handler6:
  282.         handler ict6
  283.  
  284. handler7:
  285.         handler ict7
  286.  
  287. handler8:
  288.         handler ict8
  289.  
  290. handler9:
  291.         handler ict9
  292.  
  293. handler10:
  294.         handler ict10
  295.  
  296. handler11:
  297.         handler ict11
  298.  
  299. handler12:
  300.         handler ict12
  301.  
  302. handler13:
  303.         handler ict13
  304.  
  305. handler14:
  306.         handler ict14
  307.  
  308. handler15:
  309.         handler ict15
  310.  
  311. int_common:
  312.  
  313.         push    ax
  314.  
  315. ;********************************************************
  316. ;
  317. ; Common code for all trapped INT's.
  318. ;
  319. ; At this point:
  320. ;
  321. ;   BX holds ICT address.
  322. ;   BP points to stack as follows:
  323. ;
  324. ;                   AX
  325. ;                   BX
  326. ;      (BP) ---->   BP
  327. ;               +2  IP    of caller
  328. ;               +4  CS    of caller
  329. ;               +6  FLAGS of caller
  330. ;
  331. ;********************************************************
  332.  
  333. ; At this point we get the int number in AH. We invent an esoteric INT 21H 
  334. ; value for telling the initialization code we are already here
  335.  
  336.         cmp     cs:[bx].ICT_intnum,21h          ;check interrupt # being traced
  337.         jne     notint21                        ;if not 21h go on.
  338.         mov     ax,-4[bp]                       ;get original AX
  339.         cmp     ax,iamhere                      ;is it me ?
  340.         jne     notmyint                        ;no, go on
  341.         mov     word ptr -2[bp],iamhere         ;set BX to flag
  342. notmyint:
  343.         pop     ax                              ;restore ah
  344.         push    ax                              ;restore stack
  345. notint21:
  346.         test    cs:[bx].ICT_flags,F_ENABLE      ;tracing enabled for this ICT?
  347.         jz      no_trace                        ;no, don't trace it
  348.         cmp     ah,cs:[bx].ICT_AH_lo            ;is AH within bounds?
  349.         jb      no_trace                        ;no, don't trace it
  350.         cmp     ah,cs:[bx].ICT_AH_hi
  351.         ja      no_trace                        ;no, don't trace it
  352.  
  353. ;
  354. ; See if we should check caller's CS:IP
  355. ;
  356.  
  357.         test    cs:[bx].ICT_flags,F_BELOW+F_ROM
  358.         jz      int_common3             ;no segment checks to be made
  359.  
  360.         mov     ax,2[bp]                ;get caller's IP
  361.         shr     ax,1                    ;prepare to normalize segment #
  362.         shr     ax,1
  363.         shr     ax,1
  364.         shr     ax,1
  365.         add     ax,4[bp]                ;add in segment
  366.  
  367. ;
  368. ; ------ AX now equals normalized segment #
  369. ;
  370.  
  371.         test    cs:[bx].ICT_flags,F_BELOW
  372.  
  373.         jz      int_common2             ;don't check for invoker below us
  374.         cmp     ax,cs:test_cs           ;is caller below us?
  375.         jb      no_trace                ;yes, don't trace
  376.  
  377. int_common2:
  378.  
  379.         test    cs:[bx].ICT_flags,F_ROM
  380.  
  381.         jz      int_common3             ;don't check for invoker in ROM
  382.         cmp     ax,0c000h               ;is caller in ROM?
  383.         jae     no_trace                ;yes, don't trace
  384.  
  385. int_common3:
  386.  
  387. ;
  388. ; See if we have room for this trace
  389. ;
  390.  
  391.         mov     ax,cs:trace_curr         ;get address of next entry
  392.         push    ax
  393.         add     ax,size BEFORE          ;add size of this record
  394. ;       cmp     ax,offset cs:last_byte  ;would record fit?
  395.         cmp     ax,cs:trace_end         ;would record fit?
  396.         pop     ax
  397.         jb      yes_trace               ;yes, there's room
  398.  
  399. no_trace:
  400.  
  401. ;
  402. ; We are not to trace this INT, for whatever reason.
  403. ; Just go to original handler, and return to caller (not to us).
  404. ;
  405.  
  406.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  407.         mov     word ptr cs:long_addr,ax
  408.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  409.         mov     word ptr cs:long_addr+2,ax
  410.         pop     ax
  411.         pop     bx
  412.         pop     bp
  413.         jmp     cs:long_addr    ;let original handler return to caller
  414.  
  415.  
  416. yes_trace:
  417.  
  418. ;
  419. ; We are to proceed with trace of this INT. Make trace entry.
  420. ;
  421.  
  422.         push    es
  423.         push    di
  424.  
  425. ;
  426. ; At this point:
  427. ;
  428. ;   AX holds offset to next trace entry.
  429. ;   BX holds ICT address.
  430. ;   BP points to stack as follows:
  431. ;
  432. ;                   DI
  433. ;                   ES
  434. ;                   AX
  435. ;                   BX
  436. ;      (BP) ---->   BP
  437. ;               +2  IP    of caller
  438. ;               +4  CS    of caller
  439. ;               +6  FLAGS of caller
  440. ;
  441.  
  442.         mov     di,ax                   ;set ES:DI to next trace entry
  443.         mov     ax,cs
  444.         mov     es,ax
  445.         cld                             ;forward!!!
  446.         mov     ah,cs:[bx].ICT_intnum   ;get interrupt # being traced
  447.         mov     al,cs:[bx].ICT_num      ;get ICT #, make BEFORE record type
  448.         stosw
  449.         mov     ax,-4[bp]               ;original AX
  450.         stosw
  451.         mov     ax,-2[bp]               ;original BX
  452.         stosw
  453.         mov     ax,cx
  454.         stosw
  455.         mov     ax,dx
  456.         stosw
  457.         mov     ax,-6[bp]               ;original ES
  458.         stosw
  459.         mov     ax,ds
  460.         stosw
  461.         mov     ax,ss
  462.         stosw
  463.         mov     ax,bp                   ;original SP
  464.         add     ax,2
  465.         stosw
  466.         mov     ax,si
  467.         stosw
  468.         mov     ax,-8[bp]               ;original DI
  469.         stosw
  470.         mov     ax,[bp]                 ;original BP
  471.         stosw
  472.         mov     ax,4[bp]                ;caller's CS
  473.         stosw
  474.         mov     ax,2[bp]                ;caller's IP
  475.         stosw
  476.  
  477.         mov     cs:trace_curr,di         ;save spot for next trace entry
  478.         inc     cs:[bx].ICT_hits        ;bump number of traces made for this ICT
  479.  
  480. ;
  481. ; We're done with the BEFORE trace. See if we are to do an FCB or ASCIIZ
  482. ; trace record.
  483. ;
  484.  
  485.         test    cs:[bx].ICT_flags,F_FCB
  486.         jz      no_FCB                  ;no, we are definitely not supposed to
  487.         cmp     cs:[BX].ICT_intnum,021h ;is this an INT 21h?
  488.         jnz     no_FCB                  ;no, can't trace it then
  489.  
  490. ;
  491. ; Search through ASCIIZ function table, to see if function that was called
  492. ; is one that contains an ASCIIZ pointer in DS:DX
  493. ;
  494.  
  495.         mov     ax,-4[bp]               ;get AX at time of call
  496.         push    cx
  497.         mov     di,offset cs:ASCIIZ_table
  498.         mov     cx,offset cs:ASCIIZ_end
  499.         sub     cx,di                   ;CX now has size of table
  500.         mov     al,ah                   ;get function to AL
  501.         repnz   scasb                   ;see if it's in table
  502.         pop     cx
  503.         jz      trace_ASCIIZ            ;it's there, so do ASCIIZ trace
  504.  
  505. ;
  506. ; Search through FCB function table, to see if function that was called
  507. ; is one that contains an FCB pointer in DS:DX
  508. ;
  509.  
  510.         push    cx
  511.         mov     di,offset cs:FCB_table
  512.         mov     cx,offset cs:FCB_end
  513.         sub     cx,di                   ;CX now has size of table
  514.         repnz   scasb                   ;see if it's in table
  515.         pop     cx
  516.         jnz     no_FCB                  ;no FCB or ASCIIZ trace called for
  517.  
  518. ;
  519. ; We are to do trace of FCB pointed to by DS:DX
  520. ;
  521.  
  522.         mov     al,00100000b            ;trace record number for FCB trace
  523.         mov     ah,size FCB             ;size of record
  524.         jmp     short trace_common      ;rest is common code
  525.  
  526. trace_ASCIIZ:
  527.  
  528. ;
  529. ; We are to do trace of ASCIIZ string pointed to by DS:DX
  530. ;
  531.  
  532.         mov     al,00110000b            ;trace record number for ASCIIZ trace
  533.         mov     ah,size ASCIIZ          ;size of record
  534.  
  535. trace_common:
  536.  
  537. ;
  538. ; Copy bytes from DS:DX to new ASCIIZ or FCB trace record.
  539. ;
  540. ; At this point:
  541. ;
  542. ;   AL holds trace record type, properly positioned in bits 7-4
  543. ;   AH holds size of record that we're doing (the full record)
  544. ;
  545.  
  546.         sub     ah,2                    ;minus two bytes for record header
  547.         mov     di,cs:trace_curr         ;see if there's room...
  548.         push    di
  549.         push    ax
  550.         mov     al,ah                   ;get record size to AX
  551.         xor     ah,ah
  552.         add     di,ax
  553.         cmp     di,cs:trace_end
  554.         pop     ax
  555.         pop     di
  556.         jae     no_FCB                  ;no room
  557.         push    ax                      ;save AX over this
  558.         mov     ah,cs:[bx].ICT_intnum   ;start header with interrupt #
  559.         or      al,cs:[bx].ICT_num      ;add ICT number to trace type
  560.         stosw                           ;start new record with it
  561.         pop     ax                      ;restore AX
  562.         push    cx
  563.         push    si
  564.         mov     si,dx                   ;access DS:DX as DS:SI
  565.         mov     cl,ah                   ;record size to CX
  566.         xor     ch,ch
  567.         rep     movsb                   ;that's how many to copy
  568.         pop     si
  569.         pop     cx
  570.         mov     cs:trace_curr,di         ;save offset to next record
  571.  
  572. no_FCB:                                 ;end of FCB/ASCIIZ tracing
  573.  
  574.                                         ;end of tracing, period
  575.  
  576.         test     cs:[bx].ICT_flags2,F_CALL 
  577.         jnz      call_old               ;if marked for call then call far
  578.  
  579.         ;else: for ints that don't return like 20h and 27h then just jmp far
  580.  
  581.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  582.         mov     word ptr cs:long_addr,ax
  583.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  584.         mov     word ptr cs:long_addr+2,ax
  585.  
  586.         pop     di
  587.         pop     es
  588.         pop     ax
  589.         pop     bx
  590.         pop     bp
  591.         jmp     cs:long_addr            ;invoke original handler via jump
  592.  
  593. call_old: 
  594.  
  595. ;
  596. ; Having traced all of those, now invoke original interrupt handler. Have
  597. ; it return to us, not the original caller of the interrupt.
  598. ;
  599.  
  600.         mov     cs:our_ICT,bx           ;save ICT pointer for a nanosecond
  601.         mov     al,cs:[bx].ICT_flags    ;save copy of flags that we can get to
  602.         mov     cs:our_flags,al
  603.  
  604.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  605.         mov     word ptr cs:long_addr,ax
  606.         mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  607.         mov     word ptr cs:long_addr+2,ax
  608.  
  609.         pop     di
  610.         pop     es
  611.         pop     ax
  612.         pop     bx
  613.         pop     bp
  614.         push    cs:our_ICT              ;save ICT pointer on stack
  615.         test    cs:our_flags,F_RET      ;should we push flags?
  616.         jnz     no_flags                ;no, cause they'd be left on stack
  617.         pushf                           ;yes, give handler some flags to drop
  618.  
  619. no_flags:
  620.         call    cs:long_addr            ;invoke original handler
  621.  
  622.  
  623. ;
  624. ; We're back from the real interrupt handler, and can make the "after" trace.
  625. ; Our ICT address is on stack.
  626. ;
  627.  
  628.         sti                             ;give world a crack at interrupts
  629.         nop
  630.         nop
  631.         cli                             ;*** NO INTERRUPTS!!! ***
  632.         push    bp                      ;establish stack reference
  633.         mov     bp,sp
  634.         pushf                           ;save resultant flags
  635.         push    es
  636.         push    di
  637.         push    ax
  638.         push    bx
  639.  
  640. ;
  641. ; At this point:
  642. ;
  643. ;                     BX
  644. ;                     AX
  645. ;                     DI
  646. ;                     ES
  647. ;                     FLAGS (as returned by real interrupt)
  648. ;     (BP) -------->  BP
  649. ;                     ICT address
  650. ;                     IP of caller
  651. ;                     CS of caller
  652. ;                     FLAGS of original caller
  653. ;
  654.  
  655.         mov     bx,2[bp]                ;recover ICT address
  656.         mov     di,cs:trace_curr         ;room for "after" trace entry?
  657.         push    di
  658.         add     di,size AFTER
  659. ;       cmp     di,offset cs:last_byte
  660.         cmp     di,cs:trace_end
  661.         pop     di
  662.         jae     no_after                ;no, skip it
  663.         mov     ax,cs                   ;make ES:DI point to next entry
  664.         mov     es,ax
  665.         cld                             ;forward!!!
  666.         mov     ah,cs:[bx].ICT_intnum   ;get interrupt #
  667.         mov     al,cs:[bx].ICT_num      ;get ICT #, make AFTER record type
  668.         or      al,00010000b
  669.         stosw
  670.         mov     ax,-8[bp]               ;AX at int's return
  671.         stosw
  672.         mov     ax,-10[bp]              ;BX at int's return
  673.         stosw
  674.         mov     ax,cx
  675.         stosw
  676.         mov     ax,dx
  677.         stosw
  678.         mov     ax,-4[bp]               ;ES at int's return
  679.         stosw
  680.         mov     ax,ds
  681.         stosw
  682.         mov     ax,si
  683.         stosw
  684.         mov     ax,-6[bp]               ;DI at int's return
  685.         stosw
  686.         mov     ax,[bp]                 ;BP at int's return
  687.         stosw
  688.         mov     ax,-2[bp]               ;FLAGS at int's return
  689.         stosw
  690.  
  691.         mov     cs:trace_curr,di         ;save offset to next entry
  692.  
  693. no_after:
  694.  
  695. ;
  696. ; All done making "after" trace, or we've skipped it cause there was
  697. ; no room for it.
  698. ;
  699. ; Now just exit back to the original caller.
  700. ;
  701.  
  702.         mov     al,cs:[bx].ICT_flags    ;save flags where we can get to them
  703.         mov     cs:our_flags,al
  704.         pop     bx
  705.         pop     ax
  706.         pop     di
  707.         pop     es
  708.         popf
  709.         pop     bp
  710.         pop     cs:our_ICT      ;drop ICT address without affecting flags
  711.  
  712. ;
  713. ; HOW we exit is extremely important. We must exit the same way that the
  714. ; real interrupt does.
  715. ;
  716.  
  717.         pushf                           ;save current flags in case we return them
  718.         test    cs:our_flags,F_RET
  719.         jnz     exit_ret
  720.         test    cs:our_flags,F_RET2
  721.         jnz     exit_ret2
  722.  
  723. ;
  724. ; Assume IRET.
  725. ;
  726.  
  727. exit_iret:
  728.         popf                    ;exit via IRET, reloading original flags
  729.         STI                     ;Allow interrupts now
  730.         iret
  731.  
  732. exit_ret2:
  733.         popf                    ;exit via RET 2, discarding original flags
  734.         STI                     ;Allow interrupts now
  735.         ret     2
  736.  
  737. exit_ret:
  738.         popf                    ;exit via far RET, leaving original flags
  739.         STI                     ;Allow interrupts now
  740.         ret
  741.  
  742. interrupt endp
  743.  
  744.         page
  745. ;*********************************************
  746. ;
  747. ; Handle main menu selection whose ASCII keypress is in AL.
  748. ;
  749. ; Returns: CARRY SET if we should loop back to main menu.
  750. ;          CARRY CLEAR to exit.
  751. ;
  752. ;*********************************************
  753.  
  754. do_main proc    near
  755.         push    ax
  756.         cmp     al,'P'          ;select printer?
  757.         jnz     do_main1        ;no
  758.         call    selprint        ;yes, do it
  759.         stc                     ;"Loop back to main menu" flag
  760.         jmp     short do_main9
  761.  
  762. do_main1:
  763.         cmp     al,'S'          ;select screen?
  764.         jnz     do_main2        ;no
  765.         call    selvideo        ;yes, do it
  766.         stc                     ;"Loop back to main menu" flag
  767.         jmp     short do_main9
  768.  
  769. do_main2:
  770.         cmp     al,'T'          ;Dump Traces?
  771.         jnz     do_main3        ;no
  772.         call    do_traces       ;yes, do it
  773.         stc                     ;"Loop back to main menu" flag
  774.         jmp     short do_main9
  775.  
  776. do_main3:
  777.         cmp     al,'E'          ;Enable ICT?
  778.         jnz     do_main4        ;no
  779.         mov     al,F_ENABLE     ;yes, get bit value to set/clear
  780.  
  781. do_main3b:
  782.         call    do_enable       ;enable/disable F_ENABLE per AL
  783.         stc                     ;"Loop back to main menu" flag
  784.         jmp     short do_main9
  785.  
  786. do_main4:
  787.         cmp     al,'D'          ;Disable ICT?
  788.         jnz     do_main5        ;no
  789.         mov     al,0            ;yes, get bit value to set/clear
  790.         jmp     do_main3b
  791.  
  792. do_main5:
  793.         cmp     al,'L'          ;List ICT's?
  794.         jnz     do_main6        ;no
  795.         call    disp_active     ;yes, do it
  796.         stc                     ;"Loop back to main menu" flag
  797.         jmp     short do_main9
  798.  
  799. do_main6:
  800.         cmp     al,'C'          ;Clear trace table?
  801.         jnz     do_main7        ;no
  802.         call    zap_hits        ;yes, do it
  803.         stc                     ;"Loop back to main menu" flag
  804.         jmp     short do_main9
  805.  
  806. do_main7:
  807.         cmp     al,'Q'          ;Quit?
  808.         jnz     do_main8        ;no
  809.         clc                     ;"Exit" flag
  810.         jmp     short do_main9
  811.  
  812. do_main8:
  813.         cmp     al,'F'          ;F_FCB toggle?
  814.         jnz     do_main8B       ;no
  815.         call    do_fcb          ;yes, toggle something
  816.         stc                     ;"Loop back to main menu" flag
  817.         jmp     short do_main9
  818.  
  819. do_main8b:
  820.  
  821. ; ------ Unknown selection
  822.  
  823.         stc                     ;"Loop back to main menu" flag
  824.  
  825. do_main9:
  826.         pop     ax
  827.         ret
  828. do_main endp
  829.  
  830.  
  831.         subttl  Interpretation - Misc Routines
  832.         page
  833. ;********************************************************************
  834. ;*                                                                  *
  835. ;*  This file contains the routines that interpret selected         *
  836. ;*  BEFORE trace records and print out sensible summaries of        *
  837. ;*  their meanings. This sure beats having to read a lotta hex      *
  838. ;*  function codes.                                                 *
  839. ;*                                                                  *
  840. ;*  The main routine - interp() - is called just after we've        *
  841. ;*  printed all of the trace record in hex. If this record is       *
  842. ;*  one that we know about, we should now print a one-line          *
  843. ;*  interpretation of the record. This is done via lower-level      *
  844. ;*  routines called by interp() per the INT in the record.          *
  845. ;*                                                                  *
  846. ;********************************************************************
  847.  
  848.  
  849. ;********************************************************************
  850. ;
  851. ; Interpret BEFORE trace record at [SI].
  852. ;
  853. ;********************************************************************
  854.  
  855. interp  proc    near
  856.         push    bx
  857.         push    ax
  858.         mov     ah,[SI].B_int           ;get INT type
  859.         mov     bx,offset interp_tab    ;point to table of handlers
  860.  
  861. interp2:
  862.         cmp     ah,[bx]                 ;does this handler go with this INT?
  863.         jnz     interp5                 ;no
  864.         mov     bx,1[bx]                ;yes, get handler's address
  865.         call    bx                      ;call that handler
  866.         jmp     interp9                 ;exit
  867.  
  868. interp5:
  869.         add     bx,3                    ;up to next entry in table
  870.         cmp     bx,offset interp_end    ;searched whole table yet?
  871.         jb      interp2                 ;no, try next one
  872.  
  873. interp9:
  874.  
  875.         pop     ax
  876.         pop     bx
  877.         ret
  878. interp  endp
  879.  
  880. ;
  881. ; Table of interpreters for various interrupts.
  882. ;
  883. ; Each entry is as follows:
  884. ;
  885. ;       db      <intnum>                ;interrupt number
  886. ;       dw      offset <handler>        ;address of handler to interpret this int's record
  887. ;
  888. ;
  889.  
  890. interp_tab      label   byte
  891.                 db      013h                    ;INT 13h is Diskette I/O
  892.                 dw      offset interp_13        ;handler for INT 13h
  893.                 db      020h                    ;INT 20h is DOS Program exit
  894.                 dw      offset interp_20        ;handler for INT 20h
  895.                 db      021h                    ;INT 21h is DOS Function Handler
  896.                 dw      offset interp_21        ;handler for INT 21h
  897.                 db      025h                    ;INT 025H is DOS ABSOLUTE DISK READ
  898.                 dw      offset interp_25
  899.                 db      026h                    ;INT 026H is DOS ABSOLUTE DISK WRITE
  900.                 dw      offset interp_25        ;uses same interpreter
  901.                 db      027h                    ;INT 027H is DOS TSR
  902.                 dw      offset interp_27        ;uses same interpreter
  903.                 db      02Eh                    ;INT 02EH is undoc DOS .BAT
  904.                 dw      offset interp_2E        ;uses same interpreter
  905. interp_end      label   byte                    ;end of table
  906.  
  907.         subttl  Interpretation - INT 13 (Diskette I/O)
  908.         page
  909. ;
  910. ; Tables used to interpret INT 13h  in TRACE1E.AIC
  911. ;
  912.  
  913. Floppy_or_Hard  db      0,"Floppy:",0
  914.                 db      080h,"Fixed:",080h
  915.  
  916. Cyl_or_Track    db      0,"Track:",0
  917.                 db      080h,"Cyl:",080h
  918.  
  919.  
  920. int13_line      label   byte
  921.                 db      cr,lf,"       "
  922.                 db      Edit_Call
  923. int13_F_or_H    db      0
  924.                 dw      offset Floppy_or_Hard
  925.                 dw      offset table_print
  926.                 db      Edit_Dec8
  927. int13_drive     db      0
  928.                 db      " Head:"
  929.                 db      Edit_Dec8
  930. int13_head      db      0
  931.                 db      " "
  932.                 db      Edit_Call
  933. int13_C_or_T    db      0
  934.                 dw      offset Cyl_or_Track
  935.                 dw      offset table_print
  936.                 db      Edit_Dec16
  937. int13_cyl       dw      0
  938.                 db      " Sect:"
  939.                 db      Edit_Dec8
  940. int13_sect      db      0
  941.                 db      " #Sects:"
  942.                 db      Edit_Dec8
  943. int13_numsects  db      0
  944.                 db      " "
  945.                 db      Edit_Call
  946. int13_func      db      0
  947.                 dw      offset int13_functab
  948.                 dw      offset table_print
  949.                 db      Edit_End
  950.  
  951. ;**************************************************
  952. ;
  953. ; Interpret INT 13h BEFORE trace record at [SI]
  954. ;
  955. ;**************************************************
  956.  
  957. interp_13 proc  near
  958.         push    dx
  959.         push    cx
  960.         push    ax
  961.         mov     dx,[SI].B_dx            ;get DX at time of INT
  962.         mov     al,dl                   ;Get drive #
  963.         and     al,080h                 ;isolate floppy/hard bit
  964.         mov     int13_F_or_H,al         ;use it to select device name...
  965.         mov     int13_C_or_T,al         ;...as well as cylinders/tracks
  966.         and     dl,07fh                 ;isolate drive #
  967.         mov     int13_drive,dl
  968.         mov     int13_head,dh           ;store head #
  969.         mov     cx,[SI].B_cx            ;get CX at time of INT
  970.         xor     ax,ax                   ;calc 10-bit cylinder #
  971.         mov     al,cl
  972.         shl     ax,1
  973.         shl     ax,1
  974.         mov     al,ch
  975.         mov     int13_cyl,ax            ;save as word
  976.         and     cl,00111111b            ;isolate sector #
  977.         mov     int13_sect,cl
  978.         mov     ax,[SI].B_ax            ;get AX at time of INT
  979.         mov     int13_numsects,al
  980.         mov     int13_func,ah
  981.         mov     dx,offset int13_line    ;now print edited line
  982.         call    print_edit
  983.         pop     ax
  984.         pop     cx
  985.         pop     dx
  986.         ret
  987. interp_13 endp
  988.  
  989.         subttl  Interpretation - INT 20h (DOS)
  990.         page
  991.  
  992. int20_line label byte
  993.            db      cr,lf,"       DOS: interrupt 20h - terminate program"
  994.            db      Edit_End
  995.  
  996. ;**************************************************
  997. ;
  998. ; Interpret INT 20h BEFORE trace record at [SI]
  999. ;
  1000. ;**************************************************
  1001.  
  1002. interp_20 proc  near
  1003.         push    dx
  1004.         mov     dx,offset int20_line
  1005.         call    print_edit
  1006.         pop     dx
  1007.         ret
  1008. interp_20 endp
  1009.  
  1010.  
  1011.  
  1012.  
  1013.         subttl  Interpretation - INT 21h (DOS)
  1014.         page
  1015. ;
  1016. ; Tables used in interpreting INT 21h
  1017. ;
  1018.         include trace1.aic
  1019.  
  1020.  
  1021.  
  1022. int21_line label byte
  1023.                 db      cr,lf,"       DOS: "
  1024.                 db      Edit_Call
  1025. int21_func      db      0
  1026.                 dw      offset int21_functab
  1027.                 dw      offset table_print
  1028.                 db      Edit_End
  1029.  
  1030. ;**************************************************
  1031. ;
  1032. ; Interpret INT 21h BEFORE trace record at [SI]
  1033. ;
  1034. ;**************************************************
  1035.  
  1036. interp_21 proc  near
  1037.         push    dx
  1038.         push    ax
  1039.         mov     ax,[SI].B_ax            ;get AX at time of int
  1040.         mov     byte ptr int21_func,ah  ;use it to select function
  1041.         mov     dx,offset int21_line
  1042.         call    print_edit
  1043.         pop     ax
  1044.         pop     dx
  1045.         ret
  1046. interp_21 endp
  1047.  
  1048.         subttl  Interpretation - INT 25h and 26h (Absolute disk I/O)
  1049.         page
  1050. ;
  1051. ; Tables used to interpret INT's 25h and 26h
  1052. ;
  1053.  
  1054. int25_functab   label   byte
  1055.                 db      025h,"Read",0
  1056.                 db      026h,"Write",080h
  1057.  
  1058. int25_line      label   byte
  1059.                 db      cr,lf,"       DOS Absolute "
  1060.                 db      Edit_Call
  1061. int25_func      db      0
  1062.                 dw      offset int25_functab
  1063.                 dw      offset table_print
  1064.                 db      " Drive:"
  1065.                 db      Edit_Dec8
  1066. int25_drv       db      0
  1067.                 db      " Sector:"
  1068.                 db      Edit_Dec16
  1069. int25_sect      dw      0
  1070.                 db      " #Sectors:"
  1071.                 db      Edit_Dec16
  1072. int25_numsects  dw      0
  1073.                 db      " Buf "
  1074.                 db      Edit_Word
  1075. int25_seg       dw      0
  1076.                 db      ":"
  1077.                 db      Edit_Word
  1078. int25_off       dw      0
  1079.                 db      Edit_End
  1080.  
  1081. ;**************************************************
  1082. ;
  1083. ; Interpret INT 25h or INT 26h BEFORE trace record at [SI]
  1084. ;
  1085. ;**************************************************
  1086.  
  1087. interp_25 proc  near
  1088.         push    dx
  1089.         push    ax
  1090.         mov     al,[SI].B_int           ;get INT that was done (25h or 26h)
  1091.         mov     int25_func,al           ;move to printline
  1092.         mov     ax,[SI].B_ax            ;get drive # from AL
  1093.         mov     int25_drv,al            ;move to printline
  1094.         mov     ax,[SI].B_dx            ;get starting sector # from DX
  1095.         mov     int25_sect,ax           ;move to printline
  1096.         mov     ax,[SI].B_cx            ;get # sectors from CX
  1097.         mov     int25_numsects,ax       ;move to printline
  1098.         mov     ax,[SI].B_ds            ;get buffer segment from DS
  1099.         mov     int25_seg,ax            ;move to printline
  1100.         mov     ax,[SI].B_bx            ;get buffer offset from BX
  1101.         mov     int25_off,ax            ;move to printline
  1102.         mov     dx,offset int25_line    ;now print edited line
  1103.         call    print_edit
  1104.         pop     ax
  1105.         pop     dx
  1106.         ret
  1107. interp_25 endp
  1108.  
  1109. int27_line label byte
  1110.            db      cr,lf,"       DOS: interrupt 27h - TSR"
  1111.            db      Edit_End
  1112.  
  1113. ;**************************************************
  1114. ;
  1115. ; Interpret INT 27h BEFORE trace record at [SI]
  1116. ;
  1117. ;**************************************************
  1118.  
  1119. interp_27 proc  near
  1120.         push    dx
  1121.         mov     dx,offset int27_line
  1122.         call    print_edit
  1123.         pop     dx
  1124.         ret
  1125. interp_27 endp
  1126.  
  1127. int2E_line label byte
  1128.            db      cr,lf,"       DOS: interrupt 2Eh - Undocumented .BAT service"
  1129.            db      Edit_End
  1130.  
  1131. ;**************************************************
  1132. ;
  1133. ; Interpret INT 2Eh BEFORE trace record at [SI]
  1134. ;
  1135. ;**************************************************
  1136.  
  1137. interp_2E proc  near
  1138.         push    dx
  1139.         mov     dx,offset int2E_line
  1140.         call    print_edit
  1141.         pop     dx
  1142.         ret
  1143. interp_2E endp
  1144.  
  1145.  
  1146.  
  1147.         subttl  Periscope Interrupt Interface
  1148.         page
  1149.  
  1150. ;*****************************************
  1151. ;
  1152. ; This is the interrupt handler use by Periscope to access this code.
  1153. ; It may also be called by SHIFT-PrtSc.
  1154. ;
  1155. ; On entry, AH contains function:
  1156. ;
  1157. ;       1 - 8:   User Breakpoint checks (BU 1 thru BU 8, then GT)
  1158. ;       9 - FFh: User exits (/U 9 thru /U FFh)
  1159. ;       0FFh:    Called by PrtSc
  1160. ;
  1161. ;*****************************************
  1162.  
  1163.         db      "PS"                    ;sentinel that Periscope checks for
  1164. periscope proc  far
  1165.  
  1166. ;
  1167. ; First, make very sure that we aren't being re-entered!!! This would
  1168. ; wipe out our stack which is already in use.
  1169. ;
  1170.  
  1171.         cli
  1172.         test    cs:stack_inuse,0ffh
  1173.         jz      periscope2              ;it's ok
  1174.  
  1175. periscope1:
  1176.  
  1177.         mov     al,0ffh                 ;tell Periscope "No Break, No Command to be executed"
  1178.         iret                            ;busy, call back later
  1179.  
  1180. periscope2:
  1181.  
  1182. ;
  1183. ; If we've been entered via Periscope User Break function (during single-stepping,
  1184. ; with BU 1 thru BU 8 in effect), then exit immediately. Things are slow
  1185. ; enough without us being executed when we have no Breakpoint checking to do.
  1186. ;
  1187.  
  1188.         cmp     ah,9                    ;BU 1 thru BU 8?
  1189.         jb      periscope1              ;yes, exit
  1190.  
  1191.  
  1192. ;
  1193. ; On entry to this periscope int, we ought to save everything but AX,
  1194. ; and switch to our own stack. Periscope itself doesn't require this,
  1195. ; but the PrtSc routine assumes it.
  1196. ;
  1197.  
  1198.         mov     cs:stack_inuse,0ffh     ;mark our stack busy
  1199.         mov     cs:save_ss,ss
  1200.         mov     cs:save_sp,sp
  1201.         mov     ss,cs:our_cs
  1202.         mov     sp,offset our_tos
  1203.         push    cs:save_ss              ;save old stack stuff for later
  1204.         push    cs:save_sp
  1205.         push    bx
  1206.         push    cx
  1207.         push    dx
  1208.         push    si
  1209.         push    di
  1210.         push    es
  1211.         push    ds
  1212.         push    bp
  1213.         mov     ds,cs:our_cs            ;set DS to us for assume ds:code
  1214.         sti
  1215.  
  1216. ;
  1217. ; Give user stats about trace buffer size
  1218. ;
  1219.         mov     ax,trace_bytes
  1220.         mov     word ptr size_trace,ax
  1221. ;       mov     ax,offset last_byte     ;get # free bytes
  1222.         mov     ax,trace_end            ;get # free bytes
  1223.         sub     ax,trace_curr
  1224.         mov     word ptr size_freeb,ax
  1225.         mov     dx,offset size_msg
  1226.         call    print_edit
  1227.  
  1228. periscope_menu:
  1229.  
  1230. ;
  1231. ; Now display menu and get his selection, until we are to exit
  1232. ;
  1233.  
  1234.         mov     dx,offset mainmenu
  1235.         call    print_line              ;put up main menu
  1236.         call    feed                    ;extra CRLF's for printer
  1237.         call    key                     ;get keypress
  1238.         call    do_main                 ;process it
  1239.         jc      periscope_menu          ;we are to loop back
  1240.         mov     dx,offset shadows       ;give him exit message
  1241.         call    print_line
  1242.  
  1243.  
  1244. periscope_exit:
  1245.  
  1246. ;
  1247. ; Restore regs and original stack. AX is already set to return result.
  1248. ;
  1249.  
  1250.         cli
  1251.         pop     bp
  1252.         pop     ds
  1253.         pop     es
  1254.         pop     di
  1255.         pop     si
  1256.         pop     dx
  1257.         pop     cx
  1258.         pop     bx
  1259.         pop     cs:save_sp      ;restore original stack
  1260.         pop     cs:save_ss
  1261.         mov     ss,cs:save_ss
  1262.         mov     sp,cs:save_sp
  1263.         mov     cs:stack_inuse,0        ;mark our stack not busy
  1264.         iret
  1265. periscope endp
  1266.  
  1267. mainmenu        db      cr,lf  
  1268.                 db      "  TRACE Commands:",cr,lf 
  1269.                 db      " Output to:   Trace    Trace     Sel   List    ICT   "
  1270.                 db      " Trace   Cmd  ",cr,lf
  1271.                 db      "(P)rt (S)crn (E)nable (D)isable (F)CB (T)race (L)ist "
  1272.                 db      "(C)lear (Q)uit",cr,lf,"$"
  1273.  
  1274. shadows         db      cr,lf
  1275.                 db      "Back to DOS"
  1276.                 db      cr,lf,"$"
  1277.  
  1278. size_msg        label   byte
  1279.                 db      cr,lf
  1280.                 db      "TraceBuf Bytes:"
  1281.                 db      Edit_Dec16
  1282. size_trace      dw      0
  1283.                 db      " Free Bytes:"
  1284.                 db      Edit_Dec16
  1285. size_freeb      dw      0
  1286.                 db      Edit_End
  1287.  
  1288.         subttl  INT 05 (SHIFT-PrtSc) Handler
  1289.         page
  1290. ;**************************************************
  1291. ;
  1292. ; This is another way (besides Periscope) to talk to the tracer, and
  1293. ; get it to report what it's found. This is not as clean a way as
  1294. ; via Periscope, but it beats nothing if the Periscope board isn't in
  1295. ; the system.
  1296. ;
  1297. ; This routine just calls the Periscope interrupt handler.
  1298. ;
  1299. ;**************************************************
  1300.  
  1301.         if      prt_scr
  1302.  
  1303. PrtSc   proc    far
  1304.         cli
  1305.         push    es
  1306.         push    ax
  1307.         mov     ax,050h                 ;set ES to 0050:0000
  1308.         mov     es,ax                   ;(the print-screen control byte)
  1309.         cmp     byte ptr es:[0],1       ;are we busy with previous request?
  1310.         jz      PrtSc_exit              ;yes, don't do anything
  1311.         mov     byte ptr es:[0],1       ;no, mark us busy now
  1312.         mov     ah,0ffh                 ;call Periscope INT with special arg
  1313.         int     peri_int
  1314.         mov     byte ptr es:[0],0       ;mark us not busy now
  1315.  
  1316. PrtSc_exit:
  1317.         pop     ax
  1318.         pop     es
  1319.         iret
  1320. Prtsc   endp
  1321.  
  1322.         endif
  1323.  
  1324. code    ends
  1325.         end     start
  1326. 
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.